<?php
/**
 * Storage test cases.
 *
 * @internal
 * Copyright (c) 2009, Jacob Santos
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  * Neither the name of the DragonU nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @author Jacob Santos <wordpress@santosj.name>
 * @license http://www.opensource.org/licenses/bsd-license.php New BSD license
 * @package CorePress
 * @subpackage Testing
 */

/** Include PHPUnit Framework */
require_once 'PHPUnit/Framework.php';
/** Include PHPUnit Framework Testcase */
require_once 'PHPUnit/Framework/TestCase.php';

/** CorePress Storage API */
require_once realpath(__DIR__.'/../../library/storage.php');

/**
 * Test Suite for Storage class.
 *
 * @package CorePress
 * @subpackage Testing
 */
class Storage_Test extends PHPUnit_Framework_TestCase
{
	/**
	 * @ignore
	 */
	protected function setUp()
	{
		if( ! class_exists( '\CorePress\Storage' ) )
			$this->markTestSkipped('CorePress\\Storage Class does not exist.');
	}

	/**
	 * @ignore
	 */
	protected function tearDown()
	{
		if( ! class_exists( '\CorePress\Storage' ) )
			return;

		\CorePress\Storage::$container = array();
	}

	/**
	 * Checks that the storage container attribute exists.
	 *
	 * If it does not exist then it means a regression has occurred. Or the test
	 * has not been updated after the intentional change was made.
	 */
	public function testThatStorageContainerAttributeExists()
	{
		$this->assertThat('\CorePress\Storage', $this->classHasStaticAttribute('container'));
	}

	/**
	 * Make sure that the constructor can not be accessed.
	 *
	 * @covers CorePress\Storage::__construct
	 */
	public function testThatContructorCannotBeAccessed()
	{
		$method = new ReflectionMethod('\CorePress\Storage', '__construct');
		$this->assertTrue( $method->isPrivate() );
	}

	/**
	 * Make sure the methods are static.
	 */
	public function testThatGetMethodIsStatic()
	{
		if( ! method_exists('\CorePress\Storage', 'get') )
			$this->markTestSkipped('CorePress\\Storage::get() method does not exist.');

		$method = new ReflectionMethod('\CorePress\Storage', 'get');
		$this->assertTrue( $method->isStatic() );
	}

	/**
	 * Make sure the methods are static.
	 */
	public function testThatSetMethodIsStatic()
	{
		if( ! method_exists('\CorePress\Storage', 'set') )
			$this->markTestSkipped('CorePress\\Storage::set() method does not exist.');

		$method = new ReflectionMethod('\CorePress\Storage', 'set');
		$this->assertTrue( $method->isStatic() );
	}

	/**
	 * Make sure the methods are static.
	 */
	public function testThatExistsMethodIsStatic()
	{
		if( ! method_exists('\CorePress\Storage', 'exists') )
			$this->markTestSkipped('CorePress\\Storage::exists() method does not exist.');

		$method = new ReflectionMethod('\CorePress\Storage', 'exists');
		$this->assertTrue( $method->isStatic() );
	}

	/**
	 * Make sure the methods are static.
	 */
	public function testThatRemoveMethodIsStatic()
	{
		if( ! method_exists('\CorePress\Storage', 'remove') )
			$this->markTestSkipped('CorePress\\Storage::remove() method does not exist.');

		$method = new ReflectionMethod('\CorePress\Storage', 'remove');
		$this->assertTrue( $method->isStatic() );
	}

	/**
	 * Test that the objects are being passed by reference.
	 */
	public function testThatSetObjectIsSameAsRetrievedObject()
	{
		$expected = new Storage_Test_Example_Object();

		\CorePress\Storage::set('example', $expected);

		$actual = \CorePress\Storage::get('example');

		$this->assertSame($expected, $actual, 'Object References are not working.');
	}

	/**
	 * Check that cloning works as intended.
	 */
	public function testThatSetObjectIsNotTheSameAsRetrievedObject()
	{
		$expected = new Storage_Test_Example_Object();

		$obj = clone $expected;

		\CorePress\Storage::set('example', $obj);

		$actual = \CorePress\Storage::get('example');

		$this->assertNotSame($expected, $actual, 'Object References are not working.');
	}

	/**
	 * Check that the method exists is working properly.
	 */
	public function testThatTheExistsMethodVerifiesExistingKey()
	{
		\CorePress\Storage::set('example', true);

		$this->assertThat( \CorePress\Storage::$container, $this->arrayHasKey('example'), 'Key does not exist in attribute.' );

		$this->assertTrue( \CorePress\Storage::exists('example') );
	}

	/**
	 * Check that the method exists is working properly.
	 */
	public function testTheGetMethodReturnsNullOnNonexistingKey()
	{
		\CorePress\Storage::set('example', true);

		$this->assertThat( \CorePress\Storage::$container, $this->logicalNot($this->arrayHasKey('example1')), 'Key does not exist in attribute.' );

		$this->assertFalse( \CorePress\Storage::exists('example1') );

		$this->assertNull( \CorePress\Storage::get('example1') );
	}

	/**
	 * Test that the exists method is working properly.
	 */
	public function testThatTheExistsMethodVerifiesNonexistingKeyDoesNotExist()
	{
		$this->assertThat( \CorePress\Storage::$container, $this->logicalNot($this->arrayHasKey('example')), 'Key exists that should not in attribute.' );

		$this->assertFalse( \CorePress\Storage::exists('example') );
	}

	/**
	 * Test that the removal is working properly.
	 */
	public function testRemovalOfItemIsSuccessful()
	{
		\CorePress\Storage::set('example', true);

		$this->assertThat( \CorePress\Storage::$container, $this->arrayHasKey('example'), 'Key does not exist in attribute.' );

		\CorePress\Storage::remove('example');

		$this->assertThat( \CorePress\Storage::$container, $this->logicalNot($this->arrayHasKey('example')), 'Key exists that should not in attribute.' );
	}
}

/**
 * Mock object for storage.
 *
 * @package CorePress
 * @subpackage Testing
 */
class Storage_Test_Example_Object { }